import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
import sys


def show(image,name="image"):

    h = image.shape[0]
    w = image.shape[1]

    # cv2.namedWindow('window', cv2.WINDOW_AUTOSIZE)
    cv2.imshow("%s-%d,%d"%(name,h,w), image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()




def calcuImageDark(img):
    """
    计算图片暗色像素的占比
    :param img:
    :return:
    """

    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    h, w = gray_img.shape[:2]
    dark_pix_sum = 0
    pix_sum = h * w

    # 遍历灰度图的所有像素
    for row in range(h):
        for col in range(w):
            pix = gray_img[row,col]
            if pix <= 50:# 人为设置的超参数
                dark_pix_sum +=1

    dark_prop = dark_pix_sum / pix_sum
    return dark_prop

def calcuImageArticulate(img):
    """
    计算图片清晰度（）
    模糊的照片怎么去衡量呢？根据参考大量的方案-对图像进行梯度求解然后求方差，以方差的值作为评价图像的清晰程度。
    最为常用的或者说最为经典的是拉普拉斯算子进行的梯度计算
    图像-》灰度-》拉普拉斯-》方差。
    :param img:
    :return:
    """
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    articulate = cv2.Laplacian(img_gray, cv2.CV_64F).var()

    return articulate

def calcuTwoImageSimilary(img1, img2=None):
    """
    计算两张图片的相似度
    :param img1:
    :param img2:
    :return:
    """
    # http://t1-q.mafengwo.net/s14/M00/A6/88/wKgE2l13Y5uAKqfPAADLWksB5Dw107.png
    # show(img1,"img1")
    # show(img2,"img2")

    def aHash(img):
        # 均值哈希算法
        # 缩放为8*8
        img = cv2.resize(img, (8, 8))
        # 转换为灰度图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # s为像素和初值为0，hash_str为hash值初值为''
        s = 0
        hash_str = ''
        # 遍历累加求像素和
        for i in range(8):
            for j in range(8):
                s = s + gray[i, j]
        # 求平均灰度
        avg = s / 64
        # 灰度大于平均值为1相反为0生成图片的hash值
        for i in range(8):
            for j in range(8):
                if gray[i, j] > avg:
                    hash_str = hash_str + '1'
                else:
                    hash_str = hash_str + '0'
        return hash_str

    def dHash(img):
        # 差值哈希算法
        # 缩放8*8
        img = cv2.resize(img, (9, 8))
        # 转换灰度图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        hash_str = ''
        # 每行前一个像素大于后一个像素为1，相反为0，生成哈希
        for i in range(8):
            for j in range(8):
                if gray[i, j] > gray[i, j + 1]:
                    hash_str = hash_str + '1'
                else:
                    hash_str = hash_str + '0'
        return hash_str

    def pHash(img):
        # 感知哈希算法
        # 缩放32*32
        img = cv2.resize(img, (32, 32))  # , interpolation=cv2.INTER_CUBIC

        # 转换为灰度图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # 将灰度图转为浮点型，再进行dct变换
        dct = cv2.dct(np.float32(gray))
        # opencv实现的掩码操作
        dct_roi = dct[0:8, 0:8]

        hash = []
        avreage = np.mean(dct_roi)
        for i in range(dct_roi.shape[0]):
            for j in range(dct_roi.shape[1]):
                if dct_roi[i, j] > avreage:
                    hash.append(1)
                else:
                    hash.append(0)
        return hash

    def cmpHash(hash1, hash2):
        # Hash值对比
        # 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定，但是比较的时候必须是相同的顺序。
        # 对比两幅图的指纹，计算汉明距离，即两个64位的hash值有多少是不一样的，不同的位数越小，图片越相似
        # 汉明距离：一组二进制数据变成另一组数据所需要的步骤，可以衡量两图的差异，汉明距离越小，则相似度越高。汉明距离为0，即两张图片完全一样
        n = 0
        # hash长度不同则返回-1代表传参出错
        if len(hash1) != len(hash2):
            return -1
        # 遍历判断
        for i in range(len(hash1)):
            # 不相等则n计数+1，n最终为相似度
            if hash1[i] != hash2[i]:
                n = n + 1
        return n

    def calculate(image1, image2):
        # 灰度直方图算法
        # 计算单通道的直方图的相似值
        hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
        hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
        # 计算直方图的重合度
        degree = 0
        for i in range(len(hist1)):
            if hist1[i] != hist2[i]:
                degree = degree + \
                         (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
            else:
                degree = degree + 1
        degree = degree / len(hist1)
        return degree


    def classify_hist_with_split(image1, image2, size=(256, 256)):
        # RGB每个通道的直方图相似度
        # 将图像resize后，分离为RGB三个通道，再计算每个通道的相似值
        image1 = cv2.resize(image1, size)
        image2 = cv2.resize(image2, size)
        sub_image1 = cv2.split(image1)
        sub_image2 = cv2.split(image2)
        sub_data = 0
        for im1, im2 in zip(sub_image1, sub_image2):
            sub_data += calculate(im1, im2)

        sub_data = sub_data / 3
        return sub_data


    # hash1 = aHash(img1)
    # hash2 = aHash(img2)
    # n1 = cmpHash(hash1, hash2)
    # print('均值哈希算法相似度aHash：', n1)

    # hash1 = dHash(img1)
    # hash2 = dHash(img2)
    # n2 = cmpHash(hash1, hash2)
    # print('差值哈希算法相似度dHash：', n2)

    # hash1 = pHash(img1)
    # hash2 = pHash(img2)
    # n3 = cmpHash(hash1, hash2)
    # print('感知哈希算法相似度pHash：', n3)

    n4 = classify_hist_with_split(img1, img2)
    print('三直方图算法相似度：', type(n4),n4)


def showCmpImageDistribution(img1, img2):
    hist1 = cv2.calcHist([img1], [0], None, [256], [0.0, 255.0])
    hist2 = cv2.calcHist([img2], [0], None, [256], [0.0, 255.0])
    plt.plot(range(256), hist1, 'r')
    plt.plot(range(256), hist2, 'b')
    plt.show()
    cv2.imshow('img1', img1)
    cv2.imshow('img2', img2)
    cv2.waitKey(0)

def showImageDistribution(img,name):
    hist = cv2.calcHist([img], [0], None, [256], [0.0, 255.0])
    plt.plot(range(256), hist, 'r')
    plt.show()
    cv2.imshow(name, img)
    cv2.waitKey(0)

def hist(img):
    # 用于显示图片的灰度直方图
    hist = cv2.calcHist([img], [0], None, [256], [0, 256])
    plt.subplot(121)
    plt.imshow(img, 'gray')
    plt.xticks([])
    plt.yticks([])
    plt.title("Original")
    plt.subplot(122)
    plt.hist(img.ravel(), 256, [0, 256])
    plt.show()

if __name__ == '__main__':

    imageDir = "D:\\file\\poi_video0\\frames"

    imageDir_files = os.listdir(imageDir)
    mfw_empty_img1 = cv2.imread("data/mfw_empty1.png")
    mfw_empty_img2 = cv2.imread("data/mfw_empty2.png")
    for filename in imageDir_files:
        f = os.path.join(imageDir, filename)
        if os.path.isfile(f):
            img = cv2.imread(f)
            articulate = calcuImageArticulate(img) # 计算清晰度
            dark_prop = calcuImageDark(img) # 计算暗占比

            # showImageDistribution(img,name="%.4f-%s"%(dark_prop,filename))
            # hist(img)

            calcuTwoImageSimilary(img, mfw_empty_img1)
            calcuTwoImageSimilary(img, mfw_empty_img2)
            calcuTwoImageSimilary(mfw_empty_img1, mfw_empty_img2)


            # showCmpImageDistribution(img, mfw_empty_img1)

            print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
            # break

